#pragma once

#include <list>
#include <map>
#include <vector>
#include <queue>
#include <functional>
#include <math.h>
#include <string>

#include "Square.h"
#include "SquareLine.h"

#define Debug Logger::GetInstance()->Log

//#######################################################################

struct ClientInfo
{
    std::string strName;
    UINT        nID;
};

//#######################################################################

enum PlayMode
{
    PM_SINGLE,
    PM_NET
};

//#######################################################################

struct Position
{
    UINT nRow;
    UINT nCol;
};

//#######################################################################

typedef std::list<CSquare> SquareList;
typedef SquareList::iterator SquareListIter;
typedef SquareList::const_iterator SquareListCIter;

//#######################################################################

typedef std::vector<CSquareLine> SquareLineVec;
typedef SquareLineVec::iterator SquareLineVecIter;
typedef SquareLineVec::const_iterator SquareLineVecCIter;

//#######################################################################

struct PointCompare : public std::binary_function<CPoint,CPoint,bool>
{
	bool operator()(const CPoint& lhs, const CPoint& rhs) const
	{
		return pow((double)lhs.x, 2) + pow((double)lhs.y, 2) < 
			pow((double)rhs.x, 2) + pow((double)rhs.y, 2);
	}
};

typedef std::map<CPoint, CSquare, PointCompare> SquareMap;
typedef SquareMap::iterator SquareMapIter;
typedef SquareMap::const_iterator SquareMapCIter;

//#######################################################################

typedef std::map<UINT, CSquareLine*> SquareLineMap; // UINT: top cordination of lefttop point
typedef SquareLineMap::iterator SquareLineMapIter;

//#######################################################################

enum SpinMode
{
	SM_CLOCK_WISE,
	SM_COUNTER_CLOCK_WISE
};

//#######################################################################

enum ElementState
{
	ES_FIRST = 0,
	ES_SECOND,
	ES_THIRD,
	ES_FOURTH
};

//#######################################################################

enum ElementMotion
{
	EM_LEFT = 0,
	EM_RIGHT,
	EM_DOWN,
	EM_SPIN
};

//#######################################################################

enum ElementType
{
    ET_I = 0,
    ET_K,
    ET_L,
    ET_J,
    ET_S,
    ET_Z,
    ET_O
};

//#######################################################################

struct ElementAttr
{
    ElementType     element_type;
    ElementState    element_state;
};

//#######################################################################

typedef std::queue<ElementAttr> ElementAttrQue;

//#######################################################################

// Element State define
// 1) CIElement
//		ES_FIRST:
//					#
//					#
//					#
//					#
//		ES_SECOND:
//					# # # #
//-----------------------------------------------------------------------
// 2) CJElement
//		ES_FIRST:
//					  #
//					  #
//					# #
//		ES_SECOND:	
//					#
//					# # #
//		ES_THIRD:
//					# #
//					#
//					#
//		ES_FORTH:
//					# # #
//					    #
//-----------------------------------------------------------------------
// 3) CKElement
//		ES_FIRST:
//					#
//					# #
//					#
//		ES_SECOND:	
//					# # #
//					  #
//		ES_THIRD:
//					  #
//					# #
//					  #
//		ES_FORTH:
//					  #
//					# # #
//-----------------------------------------------------------------------
// 4) CLElement
//		ES_FIRST:
//					#
//					#
//					# #
//		ES_SECOND:	
//					# # #
//					#
//		ES_THIRD:
//					# #
//					  #
//					  #
//		ES_FORTH:
//					    #
//					# # #
//-----------------------------------------------------------------------
// 5) COElement
//		ES_FIRST:
//					# #
//					# #
//-----------------------------------------------------------------------
// 6) CSElement
//		ES_FIRST:
//					  # #
//					# #
//		ES_SECOND:	
//					#
//					# #
//					  #
//-----------------------------------------------------------------------
// 7) CZElement
//		ES_FIRST:
//					# #
//					  # #
//		ES_SECOND:	
//					  #
//					# #
//					#
//-----------------------------------------------------------------------
//#######################################################################